"""
角色数据访问层
封装角色模型的数据库操作
"""
from typing import List, Optional, Dict, Any, Tuple
from tortoise.expressions import Q
from tortoise.functions import Count

from apps.auth.models.role import Role
from apps.auth.models.permission import Permission
from apps.auth.models.relations import RolePermission


class RoleRepository:
    """角色数据访问层"""
    
    @staticmethod
    async def create(role_data: Dict[str, Any]) -> Role:
        """
        创建角色
        :param role_data: 角色数据字典
        :return: 创建的角色实例
        """
        role = await Role.create(**role_data)
        return role
    
    @staticmethod
    async def get_by_id(role_id: int) -> Optional[Role]:
        """
        通过ID获取角色
        :param role_id: 角色ID
        :return: 角色实例或None
        """
        return await Role.filter(id=role_id, is_deleted=False).first()
    
    @staticmethod
    async def get_by_slug(slug: str) -> Optional[Role]:
        """
        通过标识获取角色
        :param slug: 角色标识
        :return: 角色实例或None
        """
        return await Role.filter(slug=slug, is_deleted=False).first()
    
    @staticmethod
    async def list_roles(
        page: int = 1, 
        page_size: int = 10,
        search: Optional[str] = None,
        order_by: str = "name"
    ) -> Tuple[List[Role], int]:
        """
        获取角色列表
        :param page: 页码
        :param page_size: 每页大小
        :param search: 搜索关键词(名称/标识/描述)
        :param order_by: 排序字段
        :return: 角色列表和总数
        """
        # 构建基本查询
        query = Role.filter(is_deleted=False)
        
        # 应用过滤条件
        if search:
            query = query.filter(
                Q(name__icontains=search) | 
                Q(slug__icontains=search) | 
                Q(description__icontains=search)
            )
        
        # 计算总数
        total = await query.count()
        
        # 获取分页数据
        roles = await query.order_by(order_by).offset((page - 1) * page_size).limit(page_size).all()
        
        return roles, total
    
    @staticmethod
    async def update(role: Role, update_data: Dict[str, Any]) -> Role:
        """
        更新角色信息
        :param role: 角色实例
        :param update_data: 更新的字段数据
        :return: 更新后的角色实例
        """
        # 过滤掉None值，只更新提供了的字段
        valid_updates = {k: v for k, v in update_data.items() if v is not None}
        
        # 更新角色实例字段
        for key, value in valid_updates.items():
            setattr(role, key, value)
            
        # 保存到数据库
        await role.save()
        
        return role
    
    @staticmethod
    async def update_whole(role: Role, update_data: Dict[str, Any]) -> Role:
        """
        全部更新角色信息
        :param role: 角色实例
        :param update_data: 完整的更新数据
        :return: 更新后的角色实例
        """
        # 更新所有字段，包括未提供的字段(设为默认值)
        for key, value in update_data.items():
            setattr(role, key, value)
            
        await role.save()
        
        return role
    
    @staticmethod
    async def delete(role: Role) -> None:
        """
        软删除角色
        :param role: 角色实例
        """
        await role.soft_delete()
    
    @staticmethod
    async def hard_delete(role: Role) -> None:
        """
        硬删除角色(永久删除)
        :param role: 角色实例
        """
        await role.delete()
    
    @staticmethod
    async def exists_by_id(role_id: int) -> bool:
        """
        检查角色ID是否存在
        :param role_id: 角色ID
        :return: 是否存在
        """
        return await Role.filter(id=role_id, is_deleted=False).exists()
    
    @staticmethod
    async def exists_by_slug(slug: str) -> bool:
        """
        检查角色标识是否存在
        :param slug: 角色标识
        :return: 是否存在
        """
        return await Role.filter(slug=slug, is_deleted=False).exists()
        
    @staticmethod
    async def get_role_permissions(role_id: int) -> List[Permission]:
        """
        获取角色的所有权限
        :param role_id: 角色ID
        :return: 权限列表
        """
        permissions = await Permission.filter(
            permission_roles__role_id=role_id,
            is_deleted=False
        ).all()
        
        return permissions
        
    @staticmethod
    async def assign_permission(role_id: int, permission_id: int) -> bool:
        """
        为角色分配权限
        :param role_id: 角色ID
        :param permission_id: 权限ID
        :return: 是否成功
        """
        # 检查关联是否已存在
        exists = await RolePermission.filter(
            role_id=role_id,
            permission_id=permission_id
        ).exists()
        
        if not exists:
            await RolePermission.create(
                role_id=role_id,
                permission_id=permission_id
            )
            return True
            
        return False
        
    @staticmethod
    async def remove_permission(role_id: int, permission_id: int) -> bool:
        """
        从角色中移除权限
        :param role_id: 角色ID
        :param permission_id: 权限ID
        :return: 是否成功
        """
        deleted_count = await RolePermission.filter(
            role_id=role_id,
            permission_id=permission_id
        ).delete()
        
        return deleted_count > 0
        
    @staticmethod
    async def clear_permissions(role_id: int) -> int:
        """
        清除角色的所有权限
        :param role_id: 角色ID
        :return: 清除的权限数量
        """
        deleted_count = await RolePermission.filter(
            role_id=role_id
        ).delete()
        
        return deleted_count
        
    @staticmethod
    async def get_role_users(role_id: int) -> List["User"]:
        """
        获取拥有指定角色的所有用户
        :param role_id: 角色ID
        :return: 用户列表
        """
        from apps.auth.models.user import User
        role = await Role.filter(id=role_id, is_deleted=False).first()
        if not role:
            return []
            
        return await User.filter(user_roles__role_id=role_id, is_deleted=False).all()
    
    @staticmethod
    async def assign_user(role_id: int, user_id: int) -> bool:
        """
        为角色分配用户
        :param role_id: 角色ID
        :param user_id: 用户ID
        :return: 是否成功
        """
        from apps.auth.models.relations import UserRole
        
        # 检查关联是否已存在
        exists = await UserRole.filter(user_id=user_id, role_id=role_id).exists()
        if exists:
            return True  # 已存在则视为成功
        
        # 创建新的用户-角色关联
        await UserRole.create(user_id=user_id, role_id=role_id)
        return True
    
    @staticmethod
    async def remove_user(role_id: int, user_id: int) -> bool:
        """
        移除角色中的用户
        :param role_id: 角色ID
        :param user_id: 用户ID
        :return: 是否成功
        """
        from apps.auth.models.relations import UserRole
        
        deleted_count = await UserRole.filter(
            role_id=role_id,
            user_id=user_id
        ).delete()
        
        return deleted_count > 0
    
    @staticmethod
    async def clear_users(role_id: int) -> int:
        """
        清除角色的所有用户关联
        :param role_id: 角色ID
        :return: 清除的用户关联数量
        """
        from apps.auth.models.relations import UserRole
        
        deleted_count = await UserRole.filter(
            role_id=role_id
        ).delete()
        
        return deleted_count
